package com.cman777.springc.poi.aspect;


import com.cman777.springc.common.bean.enums.YesNoCodeEnum;
import com.cman777.springc.common.bean.exception.BusinessException;
import com.cman777.springc.common.bean.response.BasePageResponse;
import com.cman777.springc.common.bean.response.JsonResult;
import com.cman777.springc.common.helper.AopUtil;
import com.cman777.springc.common.helper.DateUtil;
import com.cman777.springc.poi.annotation.ExlExport;
import com.cman777.springc.poi.annotation.ExlList;
import com.cman777.springc.poi.iface.ExlRequestIFace;
import com.cman777.springc.poi.util.POIUtil;
import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author chenzhicong
 * @time 2019/11/5 10:29
 * @description
 */
@Log4j2
@Aspect
public class ExportExlAspect {
    /**
     * 定义切面
     */
    @Pointcut("@annotation(com.cman777.springc.poi.annotation.ExlExport)")
    public void excelExport() {


    }


    /**
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("excelExport()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        Object[] args = proceedingJoinPoint.getArgs();

        Method method = AopUtil.around2Method(proceedingJoinPoint);

        boolean isNeedExport = false;

        for (Object arg : args) {
            if (ExlRequestIFace.class.isAssignableFrom(arg.getClass())) {
                ExlRequestIFace exlRequestI = (ExlRequestIFace) arg;
                if (YesNoCodeEnum.YES.equals(exlRequestI.getExportYes())) {
                    isNeedExport = true;
                }
            }
        }
        if (!isNeedExport || (method.getAnnotation(ExlExport.class) == null
                || !method.getReturnType().equals(JsonResult.class))) {
            return proceedingJoinPoint.proceed();
        }
        ExlExport exlExport = method.getAnnotation(ExlExport.class);
        //暂时处理的都是响应的JsonResult
        JsonResult jsonResult = (JsonResult) proceedingJoinPoint.proceed();
        Object object = jsonResult.getContent();
        List<Object> list = null;
        Class exlVoType = null;
        if (BasePageResponse.class.isAssignableFrom(object.getClass())) {
            list = ((BasePageResponse) object).getList();
            exlVoType = (Class) (((ParameterizedType) object.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
        } else {
            Field[] fields = object.getClass().getDeclaredFields();
            boolean canExport = false;
            for (int i = 0; i < fields.length; i++) {
                Field thisField = fields[i];
                if (!thisField.isAccessible()) {
                    thisField.setAccessible(true);
                    if (thisField.getAnnotation(ExlList.class) != null) {
                        if (!Collection.class.isAssignableFrom(thisField.get(object).getClass())) {
                            //如果添加了这个注解的不是集合
                            list = Stream.of(thisField.get(object)).filter(o->o!=null).collect(Collectors.toList());
                            exlVoType = thisField.getType();
                            canExport =true;
                            break;
                        }
                        //如果是
                        list = new ArrayList((Collection) thisField.get(object));
                        exlVoType = (Class)((ParameterizedType)thisField.getGenericType()).getActualTypeArguments()[0];
                        if (exlVoType == null || exlVoType.isAssignableFrom(Object.class)){
                            continue;
                        }else{
                            canExport =true;
                            break;
                        }
                    }
                }
            }
            if(!canExport){
                throw new BusinessException("导出失败");
            }
        }
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        String fileName = exlExport.value()+"-"+ DateUtil.format(LocalDateTime.now(),DateUtil.DateTimeFormatEnum.DATE_TIME_FORMAT_4) + ".xlsx";
        POIUtil.setResponseHead(response, fileName);
        try{
            POIUtil.exportExcel(exlVoType, list, response.getOutputStream());
        }catch (Exception e){
            log.error(e.getMessage(),e);
        }
        if(YesNoCodeEnum.YES.equals(exlExport.saveInLocal())){
            //获取JAR包目录
            ApplicationHome h = new ApplicationHome(getClass());
            File jarF = h.getSource().getParentFile();
            log.info("jarF={}",jarF.getAbsolutePath());
            File exlDir = new File(jarF, "exl");
            log.info("exlDir={}",exlDir.getAbsolutePath());
            if(!exlDir.exists()){
                exlDir.mkdir();
            }
            File exl = new File(exlDir,fileName);
            log.info("exl={}",exl.getAbsolutePath());
            if(!exl.exists()){
                exl.createNewFile();
            }
            POIUtil.exportExcel(exlVoType, list, new FileOutputStream(exl));
        }
        return new JsonResult<>();

    }

}
